//重写的命令写这里
#include "sql_util.h"
#define MAXLINE 1024


extern MYSQL * mysql;

void notCommand(task_t * task)
{
    char error1[MAXLINE] = "Without this command";
    user_info_t* user=return_user(task);
    WriteLog("execute not command.\n");
    strcpy(task->data,error1);
    transferTaskData(task);
    curr_info_t curr;
    memcpy(curr.user_name,user->name,strlen(user->name)); 
    sendn(user->net_fd,&curr,sizeof(curr));
}

void splitString(const char * pstrs, char *tokens[], int max_tokens, int * pcount) {
    int token_count = 0;
    char *token = strtok((char *)pstrs, " "); // 使用空格作为分隔符

    while (token != NULL && token_count < max_tokens - 1) { // 保留一个位置给NULL终止符
        char * pstr = (char*)calloc(1, strlen(token) + 1);
        strcpy(pstr, token);
        tokens[token_count] = pstr;//保存申请的堆空间首地址
        token_count++;
        token = strtok(NULL, " "); // 继续获取下一个token
    }
    // 添加NULL终止符
    tokens[token_count] = NULL;
    *pcount= token_count;
}

void freeStrs(char * pstrs[], int count)
{
    for(int i = 0; i < count; ++i) {
        free(pstrs[i]);
    }
}
void cdCommand(task_t * task) {


    WriteLog("execute cd command");
    char sql[2048]={0};
    char dir[2048]={0};
    char oldpwd[2048]={0};
    char parent_id[2048]={0};
    char totalpath[4096]={0};
    user_info_t* user=return_user(task);
    sprintf(dir,"%s",task->data);
    WriteLog("cdCommand----dir[%s]",dir); // 可能是.. 是一个文件夹的名字类似dir2  是dir2/dir22  是/gzt/dir2/dir22

    sprintf(sql,"select pwd from users where username='%s'",user->name);
    select_one(mysql,sql,user->pwd);//将pwd从数据库从查出来

    sprintf(sql,"SELECT parent_id FROM `virtual_files` where filename=(select pwd from users where username='%s')",user->name);
    select_one(mysql,sql,parent_id); //求出当前pwd的上级目录的id,如果是0,那么cd ..就不能再返回了
    WriteLog("cdCommand----sql[%s]-------parent_id[%s]",sql,parent_id);

    if (strcmp(dir, "..") == 0)
    {
        //cd .. 返回上一级
        if(strcmp(parent_id, "0") == 0)
        {
            //已经到根目录了,返回无效
            WriteLog("cdCommand----cant back from root dir");
            task->data[0] = '\0';
            transferTaskData(task);
            curr_info_t curr;
            memcpy(curr.user_name,user->name,strlen(user->name)); 
            memcpy(curr.pwd,user->pwd,strlen(user->pwd));
            sendn(user->net_fd,&curr,sizeof(curr));
            return;
        }
        else
        {
            //回到上一级,既parent_id当做id找到filename,也就是当前目录的上级目录,要返回的目录
            
            sprintf(sql,"select filename from virtual_files WHERE id = %s;",parent_id);
            select_one(mysql,sql,parent_id);
            //row[0] parentid 当做fileID
            //row[1] 当做目标pwd
            //getpwd(path,user->name,row[1]);
            sprintf(sql,"UPDATE `cloudservice`.`users` SET `pwd` = '%s' WHERE `username` = '%s'",parent_id,user->name);
            //sprintf(sql,"UPDATE users SET pwd = '%s' WHERE username = '%s'",parent_id,user->name);
            WriteLog("******************\n");
           
            int ret=sql_execute(mysql, sql);
            WriteLog("UPDATE--ret:[%d]------sql:[%s]\n",ret,sql);
            task->data[0] = '\0';
            transferTaskData(task);
            curr_info_t curr;
            memcpy(curr.user_name,user->name,strlen(user->name)); 
            memcpy(curr.pwd,parent_id,strlen(parent_id));
            sendn(user->net_fd,&curr,sizeof(curr));
            return;
        }
    }
    else
    {
        //WriteLog("aaa");
        if(dir[0]!='/')//不是绝对路径,需要做一个字符串拼接
        {
            getpwd(totalpath,user->name,user->pwd);//获取cd前的完整路径
            sprintf(totalpath,"%s/%s",totalpath,dir);
        }
        else
        {
            //WriteLog("bbb");
            sprintf(totalpath,"%s",dir);
        }
        WriteLog("cdCommand----totalpath[%s]",totalpath);
        if(pathIsLegal(totalpath,user->name))
        {
            WriteLog("isLegal---- path[%s] is  legal",totalpath);
            curr_info_t curr;
            //strncpy(dir, task->data, strlen(task->data));
            task->data[0] = '\0';
            transferTaskData(task);
            //WriteLog("1");
            memcpy(curr.user_name,user->name,strlen(user->name)); 
            
            //WriteLog("2");
            //更新数据库中用户表中的pwd字段
            char *lastSlash = strrchr(totalpath, '/'); // 找到最后一个斜杠
            sprintf(sql,"UPDATE `cloudservice`.`users` SET `pwd` = '%s' WHERE `username` = '%s'",lastSlash+1,user->name);
            sql_execute(mysql, sql);
            WriteLog("******************\n");
            WriteLog("UPDATE--sql:[%s]\n",sql);
            memcpy(curr.pwd,lastSlash+1,strlen(lastSlash+1));
            sendn(user->net_fd,&curr,sizeof(curr));
            //WriteLog("2");

            return;
            //freeStrs(strs, cnt);
        }
        else{
             //目录不存在 cd失败
            WriteLog("isLegal---- path[%s] is not legal",totalpath);
            WriteLog("cdCommand---- dir not exit---error");
            task->data[0] = '\0';
            transferTaskData(task);
            curr_info_t curr;
            memcpy(curr.user_name,user->name,strlen(user->name)); 
            char currpwd[2048]={0};
            getpwd(currpwd,user->name,user->pwd);
            memcpy(curr.pwd,currpwd,strlen(currpwd));
            sendn(user->net_fd,&curr,sizeof(curr));
            return ;
        }
    }



}

void getpwd(char* str,const char* username,const char* pwd)
{
    WriteLog("getpwd start---%s",str);
    char sql[2048]={0};
    char parent_id[2048]={0};
    sprintf(sql,"SELECT parent_id FROM `virtual_files` \
    where filename=(select pwd from users where username='%s')",username);
     select_one(mysql,sql,parent_id); 
    int file_id=atoi(parent_id);//3
    char path[4096]={0};
     while(file_id !=0)
    {
        sprintf(sql,"select parent_id,filename from virtual_files WHERE id = %d;",file_id);
        mysql_query(mysql,sql);
        MYSQL_RES* res = mysql_use_result(mysql);
        MYSQL_ROW row = mysql_fetch_row(res);
        if(row == NULL){
            fprintf(stderr, "Error while constructing path.\n");
            mysql_free_result(res);
            return;
        }
        char temp[1024]={0};
        file_id = atoi(row[0]);//8
        //printf("cdCommand------row[1]:%s-----file_id:%d\n",row[1],file_id);
        snprintf(temp, sizeof(temp), "/%s%s", row[1], path);
        strcpy(path, temp);
        // sprintf(temp,"/%s%s",row[1],temp);//   /dir
       // printf("cdCommand------temp:[%s]\n",path);
        mysql_free_result(res);
    }
    strcpy(str,path);
    WriteLog("getpwd end");

}

int pathIsLegal(const char* path,const char* username)
{
    //path是完整的路径 like /gzt/dir2/dir22
         WriteLog("pathIsLegal start---path[%s]",path);
        char sql[2048]={0};
        char parent_id[2048]={0};
        
        char *lastSlash = strrchr(path, '/'); // 找到最后一个斜杠
        char pwd[2048]={0};
        sprintf(pwd,"%s",lastSlash+1);  //现在pwd=dir22
        //strs[cnt-1]//new pwd  dir22
        sprintf(sql,"select parent_id from virtual_files vf join users  on vf.owner_id=users.id where vf.filename='%s' and users.username='%s'",pwd,username);
        WriteLog("pathIsLegal-----sql[%s]",sql);
        select_one(mysql,sql,parent_id);
        if(parent_id[0]=='\0'){
            //目录不存在 cd失败
        WriteLog("isLegal---- path[%s] is not legal",path);
           return 0;
        }
        int file_id=atoi(parent_id);
        while(file_id!=0)
        {
            sprintf(sql,"select parent_id from virtual_files WHERE id = %d;",file_id);
            WriteLog("pathIsLegal-----sql[%s]",sql);
            select_one(mysql,sql,parent_id);
            file_id = atoi(parent_id);//8
        }
        //WriteLog("isLegal---- path[%s] is  legal",path);
        return 1;

}

void lsCommand(task_t * task) {

    char sql[2048]={0};
    char buff[2048]={0};
    char pwd[2048]={0};
    user_info_t* user=return_user(task);
    sprintf(sql,"select pwd from users where username='%s'",user->name);
    WriteLog("lsCommand----sql[%s]",sql);
    select_one(mysql,sql,pwd);
    WriteLog("lsCommand----pwd[%s]",pwd);

   // sprintf(sql,"select filename,filesize,type from virtual_files where parent_id =(select vf.id from virtual_files vf join users un on vf.owner_id=un.id and un.pwd=vf.filename where un.pwd='%s')",pwd);
    sprintf(sql,"select filename from virtual_files where parent_id =(select vf.id from virtual_files vf join users un on vf.owner_id=un.id and un.pwd=vf.filename where un.username='%s')",user->name);
    select_multiple(mysql,sql,buff,2048);
    //QueryResult* result= execute_query(mysql,sql);
    WriteLog("lsCommand----sql[%s]",sql);
    WriteLog("lsCommand----buff[%s]",buff);
    strncpy(task->data,buff,sizeof(task->data) - 1);
    task->data[sizeof(task->data) - 1] = '\0'; // 确保以空字符结尾
    transferTaskData(task);
    curr_info_t curr;
    memcpy(curr.user_name,user->name,strlen(user->name)); 
    sendn(user->net_fd,&curr,sizeof(curr));

}

void pwdCommand(task_t * task)
{   //by sjk 2024.6.23
    char sql[2048]={0};
    char totalpath[4096]={0};
    WriteLog("execute pwd command");

    user_info_t* user=return_user(task);

    sprintf(sql,"select pwd from users where username='%s'",user->name);
    select_one(mysql,sql,user->pwd);//将pwd从数据库从查出来

    getpwd(totalpath,user->name,user->pwd);//获取cd前的完整路径
    sprintf(totalpath,"%s/%s",totalpath,user->pwd);

    strcpy(task->data,totalpath);
    curr_info_t curr;
    memcpy(curr.user_name,user->name,strlen(user->name)); 
    memcpy(curr.pwd,user->pwd,strlen(user->pwd));
    transferTaskData(task);
    sendn(user->net_fd,&curr,sizeof(curr));
    WriteLog("pwd finish");
    return ;
}

void pwdCommand_lhm(task_t * task) {
    WriteLog("execute pwd command");
    user_info_t* user = return_user(task);

    char* userName = user->name;
    char* pwd = user->pwd;
    char sql[4096];
    char outcome[4096]; //保存完整路径结果
    char str[128]={0};//接收数据库字段返回值
    if(strcmp(userName,pwd)==0){
        curr_info_t curr;
        memcpy(curr.user_name,user->name,strlen(user->name));
        snprintf(outcome,sizeof(outcome),"/%s\n",pwd);
        strcpy(task->data,outcome);
        transferTaskData(task);
        sendn(user->net_fd,&curr,sizeof(curr));
        WriteLog("pwd finish");
        return;
    }
    
    //往下肯定有多级目录
    char path[1024]="";
    strcpy(path,pwd);

    snprintf(sql,sizeof(sql),"SELECT id FROM users WHERE username = '%s';",userName);
    WriteLog("pwdCommand----sql[%s]",sql);
    select_one(mysql,sql,str);
    int owner_id = atoi(str);

    snprintf(sql,sizeof(sql),"SELECT parent_id FROM virtual_files WHERE filename = '%s' AND owner_id = %d;",pwd, owner_id);
    memset(str,0,sizeof(str));
    WriteLog("pwdCommand----sql[%s]",sql);
    select_one(mysql,sql,str);
    int file_id = atoi(str);
    
    while(file_id != 0){
        snprintf(sql,sizeof(sql),"SELECT parent_id, filename FROM virtual_files WHERE id = %d AND owner_id = %d;",file_id, owner_id);
        WriteLog("pwdCommand----sql[%s]",sql);
        mysql_query(mysql,sql);
        MYSQL_RES* res = mysql_use_result(mysql);
        MYSQL_ROW row = mysql_fetch_row(res);
        if(row == NULL){
            fprintf(stderr, "Error while constructing path.\n");
            mysql_free_result(res);
            return;
        }

        file_id = atoi(row[0]);
        char temp[4096];
        snprintf(temp, sizeof(temp), "%s/%s", row[1], path);
        strcpy(path, temp);

        mysql_free_result(res);
    }
    snprintf(outcome,sizeof(outcome),"/%s\n",path);
    strcpy(task->data,outcome);

    curr_info_t curr;
    memcpy(curr.user_name,user->name,strlen(user->name)); 
    //memcpy(curr.pwd,strrchr(outcome, '/')+1,strlen(strrchr(outcome, '/')+1)-1);//截取outcome的最后一个/后面的文件夹名字 by sjk 6.23
    transferTaskData(task);
    sendn(user->net_fd,&curr,sizeof(curr));
    WriteLog("pwd finish");
}


void mkdirCommand(task_t * task) {
    WriteLog("execute mkdir command.\n");
    char sql[4096]; // sql 查询语句
    char str[128] = {0}; // 接收数据库字段返回值
    // 查询用户信息
    user_info_t* user = return_user(task);
    char* pwd = user->pwd; //当前目录名
    char* userName = user->name; // 当前用户名

    snprintf(sql,sizeof(sql),"SELECT id FROM users WHERE username = '%s';",userName);
    WriteLog("mkdirCommand----sql[%s]",sql);
    select_one(mysql,sql,str);
    int owner_id = atoi(str);

    snprintf(sql,sizeof(sql),"SELECT id FROM virtual_files WHERE filename = '%s' AND owner_id = %d;",pwd, owner_id);
    WriteLog("mkdirCommand----sql[%s]",sql);
    memset(str,0,sizeof(str));
    select_one(mysql,sql,str);
    int parent_id = atoi(str);//获取待创建目录的 parent_id
                              //
    char dir[128]; // 获取待创建目录的 filename
    strncpy(dir,task->data,strlen(task->data));

    //先判断是否已经存在该目录
    snprintf(sql,sizeof(sql),"SELECT id FROM virtual_files WHERE filename = '%s' AND owner_id = %d AND parent_id = %d;",dir,owner_id,parent_id);
    mysql_query(mysql,sql);
    MYSQL_RES* res = mysql_use_result(mysql);
    MYSQL_ROW row = mysql_fetch_row(res);
    if(row != NULL){
        char outcome[4096];
        snprintf(outcome,sizeof(outcome),"The same directory already exists...");
        strncpy(task->data,outcome,strlen(outcome));
        transferTaskData(task);
        curr_info_t curr;
        memcpy(curr.user_name,user->name,sizeof(user->name));
        sendn(user->net_fd,&curr,sizeof(curr));
        return;
    }

    // 往下需要创建新的目录文件
    snprintf(sql, sizeof(sql), "INSERT INTO virtual_files (parent_id, filename, owner_id, md5, filesize, type) values "
             "(%d,'%s',%d,0,0,'d');",parent_id,dir,owner_id);
    WriteLog("mkdirCommand----sql[%s]",sql);
    sql_execute(mysql, sql);

    memset(task->data,0,sizeof(task->data));
    transferTaskData(task);
    curr_info_t curr;
    memcpy(curr.user_name,user->name,strlen(user->name)); 
    sendn(user->net_fd,&curr,sizeof(curr));
    WriteLog("mkdir finfsh");
    // 更新 USERS 表的 pwd 信息
    //snprintf(sql,MAXLINE,"UPDATE users SET pwd='%s' WHERE username='%s';",dir,userName);
    //sql_execute(mysql,sql);
}

void recursice_del(MYSQL* mysql,int file_id,int owner_id){
    char sql[1024];
    snprintf(sql,sizeof(sql),"SELECT id,filename FROM virtual_files "
             "WHERE parent_id = %d AND owner_id = %d;",file_id,owner_id);
    mysql_query(mysql,sql);
    MYSQL_RES* res = mysql_store_result(mysql);
    MYSQL_ROW row;
    int child_id;
    while((row = mysql_fetch_row(res)) != NULL){
        child_id = atoi(row[0]);
        recursice_del(mysql,child_id,owner_id);
    }

    mysql_free_result(res);

    snprintf(sql,sizeof(sql),"DELETE FROM virtual_files WHERE id = %d AND owner_id = %d;",file_id,owner_id);
    mysql_query(mysql,sql);
}

void rmdirCommand(task_t * task) {
    user_info_t* user = return_user(task);
    char* userName = user->name;
    char* del_dir = task->data;
    char sql[4096];
    char str[128]="";
    char outcome[4096]="";

    snprintf(sql,sizeof(sql),"SELECT id FROM users WHERE username = '%s';",userName);
    WriteLog("rmdirCommand----sql[%s]",sql);
    select_one(mysql,sql,str);
    int owner_id = atoi(str);

    snprintf(sql,sizeof(sql),"SELECT id FROM virtual_files WHERE filename = '%s' AND owner_id = %d;",del_dir, owner_id);
    memset(str,0,sizeof(str));
    WriteLog("rmdirCommand----sql[%s]",sql);
    select_one(mysql,sql,str);
    if(strcmp(str,"") == 0){ //目录不存在的情况
        snprintf(outcome,sizeof(outcome),"Cannot remove '%s': No such file or directory",del_dir);
        strcpy(task->data,outcome);
        transferTaskData(task);
        curr_info_t curr;
        memcpy(curr.user_name,user->name,strlen(user->name)); 
        sendn(user->net_fd,&curr,sizeof(curr));
        return;
    }

    //往下走存在目标目录
    int file_id = atoi(str); 

    recursice_del(mysql,file_id,owner_id);

    snprintf(outcome, sizeof(outcome), "Directory '%s' and its contents have been deleted", del_dir);
    strcpy(task->data, outcome);
    transferTaskData(task);
    curr_info_t curr;
    memcpy(curr.user_name,user->name,strlen(user->name)); 
    sendn(user->net_fd,&curr,sizeof(curr));
    WriteLog("rmdir finish");
}


void getsCommand(task_t * task) {
    WriteLog("execute gets command.\n");
    //获取文件名
    char* filename = task->data;
    //在虚拟文件表中查找md5
    char sql[1000] = {0};
    char md5[33] = {0};
    char str[] = {0};
    snprintf(sql, sizeof(sql), "SELECT md5 FROM virtual_files WHERE filename = '%s'", filename);
    WriteLog("getsCommand----sql[%s]",sql);
    select_one(mysql, sql, str);
    strcpy(md5, str);
    printf("md5: %s\n", md5);

    //进行文件的发送
    //先发送文件名
    int len = -1;
    len = strlen(filename);
    int fd = open(md5, O_RDWR);
    if(fd == -1){
        perror("open");
        send(task->peerfd, &len, sizeof(len), 0);
        return;
    }
    send(task->peerfd, &len, sizeof(len), 0);
    sendn(task->peerfd, filename, len);

    off_t currLength = 0;//获取开始传输文件位置
    recv(task->peerfd, &currLength, sizeof(currLength), 0);

    //获取文件的长度
    struct stat fileInfo;
    memset(&fileInfo, 0, sizeof(fileInfo));
    fstat(fd, &fileInfo);
    off_t length = fileInfo.st_size;
    printf("file length: %ld\n", length);

    //发送文件的长度
    sendn(task->peerfd, &length, sizeof(length));

    //对文件进行偏移
    int ret = lseek(fd, currLength, SEEK_SET);
    if(ret != 0){
        perror("lseek");
    }
    length -= currLength;

    //发送文件内容
    //发送小文件
    //gzt-6.19
    if(length < 104857600){
        char buff[1000] = {0};
        off_t currSize = 0;
        off_t lastSize = 0;
        off_t splice = length / 100;
        while(1){
            memset(&buff, 0, sizeof(buff));
            int ret = read(fd, buff, sizeof(buff));
            if(ret <= 0){
                break;
            }
            ret = sendn(task->peerfd, buff, strlen(buff));
            if(ret == -1){
                break;
            }
            currSize += ret;
            if(currSize - lastSize > splice){
                printf("has complete %5.2lf%%\r", (double)currSize / length * 100);
                fflush(stdout);
                lastSize = currSize;
            }
        }
        printf("has complete 100.00%%\n");
        printf("send file over.\n");
        close(fd);
        return;
    }

    //发送大文件
    off_t offset = 0;
    off_t splice = 4096 * 128;
    off_t Splice = length / 100;
    off_t lastSize = 0;
    while(offset < length){
        char * pMap = (char*)mmap(NULL, splice, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
        if(pMap) {
            //pMap代表的是内核中的文件缓冲区
            //sockfd代表的是套接字缓冲区
            int ret = send(task->peerfd, pMap, splice, 0);
            offset += ret;
            if(offset - lastSize > Splice){
                printf("has complete %5.2lf%%\r", (double)offset / length * 100);
                fflush(stdout);
                lastSize = offset;
            }
        }
    }
    printf("has complete 100.00%%\n");
    printf("send file over.\n");
    close(fd);//关闭文件

    /*user_info_t* user = return_user(task);
    printf("username: %s\n", user->name);
    curr_info_t curr;
    memcpy(curr.user_name, user->name, strlen(user->name));
    transferTaskData(task);
    sendn(user->net_fd, &curr, sizeof(curr));*/
    return;
}


//gzt:客户端上传文件
void putsCommand(task_t * task) {
    WriteLog("execute puts command.\n");

    char sql[1000] = {0};//用于存储sql指令
    char filename[100] = {0};
    int len = 0;
    int ret = recv(task->peerfd, &len, sizeof(len), 0);//先接长度
    if(len == -1){
        printf("error in client command.\n");
        return;
    }
    ret = recvn(task->peerfd, filename, len);//再接内容
    printf("filename:%s\n", filename);

    //再获取的是文件长度
    off_t length = 0;
    recvn(task->peerfd, (char*)&length, sizeof(length));
    printf("file length: %ld\n", length);

    //接收MD5码
    char md5[100] = {0};
    recv(task->peerfd, md5, sizeof(md5), 0);
    printf("md5: %s\n", md5);
    //判断虚拟文件表中是否存在相同文件
    int sig = 0;
    int fd = open(md5, O_RDONLY);
    if(fd == -1){
        sig = 1;
    }
    close(fd);

    //给client发送信号，若为1，则表示需要传输文件内容
    send(task->peerfd, &sig, sizeof(sig), 0);

    //若信号为1，则证明文件表内不存在该文件，需要插入
    if(sig == 1){
        memset(sql, 0, sizeof(sql));
        snprintf(sql, sizeof(sql), "INSERT INTO server_files (md5) VALUES('%s')", md5);
        sql_execute(mysql, sql);

        int wfd = open(md5, O_CREAT | O_RDWR, 0644);
        if(wfd == -1){
            perror("open");
            return;
        }

        //最后接收文件内容
        //接收小文件
        if(length < 104857600){
            off_t splice = length / 100;
            off_t currSize = 0;
            off_t lastSize = 0;
            char buff[1000] = {0};
            off_t left = length;
            while(left > 0) {
                left = length - currSize;
                if(left >= 1000) {
                    ret = recvn(task->peerfd, buff, sizeof(buff));//再接文件内容
                } else if(left < 1000 && left > 0){
                    ret = recvn(task->peerfd, buff, left);
                } else {
                    break;
                }
                //最后再写入本地
                ret = write(wfd, buff, ret);
                currSize += ret;
                if(currSize - lastSize > splice) {
                    printf("has complete %5.2lf%%\r", (double)currSize / length * 100);
                    fflush(stdout);
                    lastSize = currSize;
                }
            }
            printf("has complete 100.00%%\n");
            close(wfd);
        }else{
            //接收大文件
            off_t offset = 0;
            off_t splice = 4096 * 128;
            off_t Splice = length / 100;
            off_t lastSize = 0;
            ftruncate(wfd, length);
            while(offset < length){
                if(offset + splice > length){
                    splice = length - splice;
                }
                char * pMap = (char*)mmap(NULL, splice, PROT_READ|PROT_WRITE, MAP_SHARED, wfd, offset);
                if(pMap) {//映射成功
                    //clientfd代表的是内核态套接字的缓冲区
                    //pMap代表的是内核文件缓冲区
                    int ret = recv(task->peerfd, pMap, splice, MSG_WAITALL);
                    offset += ret;
                    if(offset - lastSize > Splice){
                        printf("has complete %5.2lf%%\r", (double)offset / length * 100);
                        fflush(stdout);
                        lastSize = offset;
                    }
                }
            }
            printf("has complete 100.00%%\n");
            printf("recv file over.\n");
            close(wfd);
        }
    }
    //获取parent_id
    char str[100] = {0};
    memset(&sql, 0, sizeof(sql));
    int parent_id = 0;
    snprintf(sql, sizeof(sql), "SELECT virtual_files.id "
             "FROM virtual_files CROSS JOIN users ON virtual_files.owner_id = users.id "
             "WHERE virtual_files.filename = users.pwd");
    WriteLog("putsCommand----sql[%s]",sql);
    select_one(mysql, sql, str);
    if(strlen(str) != 0){
        parent_id = atoi(str);
    }

    //判断是否需要在virtual_files表中插入数据
    memset(&sql, 0,sizeof(sql));
    memset(&str, 0, sizeof(str));
    snprintf(sql, sizeof(sql), "SELECT id FROM virtual_files WHERE "
             "filename = '%s' AND md5 = '%s' AND parent_id = '%d'", filename, md5, parent_id);
    WriteLog("putsCommand----sql[%s]",sql);
    select_one(mysql, sql, str);
    if(strlen(str) != 0){
        return;
    }

    //向虚拟文件表中插入数据
    user_info_t* user = return_user(task);
    char* username = user->name;
    memset(sql, 0, sizeof(sql));
    memset(str, 0, sizeof(str));
    snprintf(sql, sizeof(sql), "INSERT INTO virtual_files (parent_id, filename, owner_id, md5, filesize, type) "
                        "SELECT '%d', '%s', users.id, '%s', '%ld', 'f' "
                        "FROM users WHERE users.username = '%s'", parent_id, filename, md5, length, username);
    sql_execute(mysql, sql);
    WriteLog("end sql_execute\n");

    return;
}
